package com.ideaaedi.commonspring.lite.monitor;

import org.springframework.core.Ordered;

/**
 * 耗时记录器
 *
 * @author <font size = "20" color = "#3CAA3C"><a href="https://gitee.com/JustryDeng">JustryDeng</a></font> <img
 * src="https://gitee.com/JustryDeng/shared-files/raw/master/JustryDeng/avatar.jpg" />
 * @since 2100.10.7.LTS17
 */
public @interface TimeWatcher {
    
    /** 默认格式 */
    String POINTCUT_FORMAT =
            "("
                + "@annotation(com.ideaaedi.commonspring.lite.monitor.WatchTime)"
                + "%s"
            + ")"
            + "%s";
    
    /** 默认切点 */
    String DEFAULT_POINTCUT = String.format(POINTCUT_FORMAT, "", "");
    
    /**
     * 需要包含的methodReference前缀
     * <pre>
     *
     *  为空则表示全部包含
     *
     *  methodReference形如：com.ideaaedi.commonspring.aop.WatchTimeAdvice#init
     * </pre>
     */
    String[] includePrefixes() default {};
    
    /**
     * 需要排除的methodReference前缀
     * <pre>
     *
     *  为空则表示都不需要排除
     *
     *  methodReference形如：com.ideaaedi.commonspring.aop.WatchTimeAdvice#init
     * </pre>
     */
    String[] excludePrefixes() default {};
    
    /**
     * aop的优先级
     */
    int aopPriority() default Ordered.HIGHEST_PRECEDENCE;
    
    /**
     * 是否禁用最外层的过滤器（注：一般的，如果自己已经在自己的过滤器中做了默认过滤器的操作，那么可以禁用默认的过滤器）
     * <pre>
     * 默认过滤器会做这些操作：
     *     1.请求进来时，将初始化计时器
     *     2.请求结束时，将打印耗时信息
     *  默认过滤器代码形如， {@code
     *     @Override
     *     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
     *             ServletException {
     *         try {
     *             WatchTimeUtil.Manager.init();
     *             String requestUri = "";
     *             if (request instanceof HttpServletRequest httpServletRequest) {
     *                 requestUri = httpServletRequest.getRequestURI();
     *             }
     *             WatchTimeUtil.start("request-uri ->  " + requestUri);
     *             chain.doFilter(request, response);
     *         } finally {
     *             try {
     *                 WatchTimeUtil.stop();
     *                 log.info("consume time -> {}", prettyResult ? WatchTimeUtil.prettyResult() : WatchTimeUtil.result());
     *             } catch (Exception e) {
     *                 log.warn("WatchTimeUtil.stop occur exception. e.getMessage() -> {}", e.getMessage());
     *             }
     *             WatchTimeUtil.Manager.clear();
     *         }
     *     }
     *  }
     * {@code
     * }
     * </pre>
     */
    boolean disableFilter() default false;
    
    /**
     * 最外层过滤器的优先级
     * <pre>
     * 当{@link #disableFilter}为false时，生效
     * </pre>
     */
    int filterPriority() default Ordered.HIGHEST_PRECEDENCE;
    
    /**
     * 是否美化打印结果
     * <pre>
     * 当{@link #disableFilter}为false时，生效
     * </pre>
     */
    boolean prettyResult() default true;
    
    /**
     * 切点and匹配
     * <pre>
     * {@code
     * 默认切点是：
     * @Pointcut(
     *        "("
     *             + "@annotation(com.ideaaedi.commonspring.lite.monitor.WatchTime)"
     *         + ")"
     * )
     *
     * 在最后面增加 && 拼接你配置的切点。假设你配置的切点是execution(* *..*RequestHandler.invoke(..))，那么拼接后形如：
     * @Pointcut(
     *        "("
     *             + "@annotation(com.ideaaedi.commonspring.lite.monitor.WatchTime)"
     *         + ")"
     *         + " && "
     *         + "execution(* *..*RequestHandler.invoke(..))"
     * )
     * }
     * </pre>
     */
    String[] pointcutAnd() default {};

    /**
     * 切点or匹配
     * <pre>
     * {@code
     * 默认切点是：
     * @Pointcut(
     *        "("
     *             + "@annotation(com.ideaaedi.commonspring.lite.monitor.WatchTime)"
     *         + ")"
     * )
     *
     * 在括号中增加 || 拼接你配置的切点。假设你配置的切点是execution(* *..*RequestHandler.invoke(..))，那么拼接后形如：
     * @Pointcut(
     *        "("
     *             + "@annotation(com.ideaaedi.commonspring.lite.monitor.WatchTime)"
     *             + " || "
     *             + "execution(* *..*RequestHandler.invoke(..))"
     *         + ")"
     * )
     * }
     * </pre>
     */
    String[] pointcutOr() default {"execution(* *..*Controller.*(..))"};
}
